package com.jin.lazytool;

import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.NativeHookException;
import com.jin.lazytool.componment.NumberField;
import com.jin.lazytool.customevent.*;
import com.jin.lazytool.entity.IEvent;
import com.jin.lazytool.entity.LoopEndEvent;
import com.jin.lazytool.listener.KeyboardListener;
import com.jin.lazytool.listener.MouseClickedListener;
import com.jin.lazytool.listener.MouseMotionListener;
import com.jin.lazytool.rewritte.ChoiceBoxSelectModel;
import com.jin.lazytool.rewritte.FxJinTask;
import com.jin.lazytool.task.JinTask;
import com.jin.lazytool.task.JinTaskGroup;
import com.jin.lazytool.task.RunJinTask;
import com.jin.lazytool.task.ThreadUtils;
import com.jin.lazytool.utils.*;
import com.melloware.jintellitype.JIntellitype;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.util.StringConverter;

import java.awt.event.KeyEvent;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;

public class JinTaskController implements Initializable {

    private static KeyboardListener keyboardListener;
    private static MouseClickedListener mouseClickedListener;
    private static MouseMotionListener mouseMotionListener;

    public static JinTaskController controller;
    public JinTaskController(){
        controller = this;
    }

    @FXML
    private Accordion accordion;

    @FXML
    private Button addTask;
    @FXML
    private Button removeTask;
    @FXML
    private Button refreshTask;
    @FXML
    private Button saveTask;

    @FXML
    private Button collect;

    @FXML
    private Button execute;
    @FXML
    private Button stopExecute;

    @FXML
    private Button stop;

    @FXML
    private Button addEvent;

    @FXML
    private ChoiceBox<JinTask> taskChoice;


    // 正在收集动作
    public static boolean collectingFlag = false;

    @FXML
    void addConfig(ActionEvent event){
        Dialog<?> dialog = new Dialog<>();
        ButtonType sureButton = new ButtonType("保存", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(sureButton, ButtonType.CANCEL);
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        Label address = new Label("鼠标捕捉间隔/毫秒");
        NumberField addressValue = new NumberField(ConfigUtils.getMouseMoveTime());
        addressValue.setPromptText("默认1秒");
        grid.addRow(0,address,addressValue);

        Label addressDrag = new Label("鼠标拖拽间隔/毫秒");
        NumberField addressValueDrag = new NumberField(ConfigUtils.getMouseDragTime());
        addressValueDrag.setPromptText("默认10毫秒");
        grid.addRow(1,addressDrag,addressValueDrag);

        dialog.getDialogPane().setContent(grid);

        Optional<?> result = dialog.showAndWait();
        result.ifPresent(o -> {
           if("保存".equals(((ButtonType)o).getText())){
               DataUtils.getConfig().put(ConfigUtils.MOUSE_MOVE_TIME_KEY,addressValue.getValue());
               DataUtils.getConfig().put(ConfigUtils.MOUSE_DRAG_TIME_KEY,addressValueDrag.getValue());
               DataUtils.saveConfig();
           }
        });
    }

    @FXML
    void extractMousePoint(ActionEvent event){
        NumberField numberField = new NumberField(0);
        numberField.setMin(0);
        numberField.setPromptText("单位/秒");
        AtomicBoolean openFlag = new AtomicBoolean(false);
        JinUtils.getDialog("延迟弹出",(grid,dialog)->{
            grid.addRow(0,new Label("延迟时间/s"),numberField);
        },()->{
            openFlag.set(true);
        });
        if(openFlag.get()){
            try {
                Thread.sleep(numberField.getNullDefaultValue() * 1000);
            } catch (InterruptedException ignored) {

            }
            ExtractMousePointUtil.show();

        }
    }

    @FXML
    void about(ActionEvent event){
        Dialog<?> dialog = new Dialog<>();

        Window window = dialog.getDialogPane().getScene().getWindow();
        Stage stage = (Stage) window;
        stage.getIcons().add(new Image("dialog.png"));

        dialog.setTitle("关于");

        ButtonType sureButton = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(sureButton);
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        grid.addRow(0,new Label("作者：Mr.Hu") );
        grid.addRow(1,new Label("邮箱：980254542@qq.com") );

        dialog.getDialogPane().setContent(grid);

        Optional<?> result = dialog.showAndWait();
        result.ifPresent(o -> {

        });
    }
    @FXML
    void operatingManual(ActionEvent event){
        Dialog<?> dialog = new Dialog<>();

        Window window = dialog.getDialogPane().getScene().getWindow();
        Stage stage = (Stage) window;
        stage.getIcons().add(new Image("dialog.png"));

        dialog.setTitle("操作手册");

        ButtonType sureButton = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(sureButton);
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        grid.addRow(grid.getRowCount() ,new Label("""
                入门：>点击新增按钮，添加任务
                         >点击收集按钮，键盘鼠标按下对应的操作
                         >连按2次Esc
                         >点击保存
                         >点击执行按钮。
                """));
        grid.addRow(grid.getRowCount() ,new Label("菜单栏：") );
        grid.addRow(grid.getRowCount() ,new Label("  配置->配置->鼠标捕捉间隔：鼠标移动被记录的时间间隔") );
        grid.addRow(grid.getRowCount() ,new Label("  配置->配置->鼠标拖拽间隔：鼠标按下左键后移动被记的时间间隔"));
        grid.addRow(grid.getRowCount() ,new Label("  工具->摄取坐标->获取屏幕中某个位置的坐标，用于计算坐标"));
        grid.addRow(grid.getRowCount() ,new Label("  帮助：字面意思"));
        grid.addRow(grid.getRowCount() ,new Label("内容页："));
        grid.addRow(grid.getRowCount() ,new Label("  任务列表：保存的任务列表"));
        grid.addRow(grid.getRowCount() ,new Label("  新增 按钮：添加任务"));
        grid.addRow(grid.getRowCount() ,new Label("  删除 按钮：删除任务"));
        grid.addRow(grid.getRowCount() ,new Label("  重置 按钮：重置已经保存的数据"));
        grid.addRow(grid.getRowCount() ,new Label("  保存 按钮：保存数据，数据做修改后保存后生效"));
        grid.addRow(grid.getRowCount() ,new Label("  收集 按钮：收集鼠标键盘动作，点击收集后开始收集，按下两次Esc(键盘左上角按钮)结束收集"));
        grid.addRow(grid.getRowCount() ,new Label("  停止 按钮：和上一个(按下两次Esc)一致"));
        grid.addRow(grid.getRowCount() ,new Label("  执行 按钮：执行收集的鼠标键盘动作"));
        grid.addRow(grid.getRowCount() ,new Label("  执行 按钮：停止执行收集的鼠标键盘动作(不回立即停止,会把当前正在执行的一个动作完成后停止"));
        grid.addRow(grid.getRowCount() ,new Label("  停止执行 按钮：停止执行收集的鼠标键盘动作(不回立即停止,会把当前正在执行的一个动作完成后停止"));
        grid.addRow(grid.getRowCount() ,new Label("  分组：为了方便手工操作，按照分组归类，执行按照从上到下顺序执行"));
        grid.addRow(grid.getRowCount() ,new Label("  分组中的按钮："));
        grid.addRow(grid.getRowCount() ,new Label("    新增事件 按钮：手工新增鼠标键盘动作"));
        grid.addRow(grid.getRowCount() ,new Label("    收集 按钮：通上边收集按钮，这里收集的动作会放在当前分组下"));
        grid.addRow(grid.getRowCount() ,new Label("    备注 按钮：修改当前分组的备注"));
        grid.addRow(grid.getRowCount() ,new Label("    移除 按钮：移除当前分组"));
        grid.addRow(grid.getRowCount() ,new Label("      分组中的列表：事件列表"));
        grid.addRow(grid.getRowCount() ,new Label("      分组中事件按钮："));
        grid.addRow(grid.getRowCount() ,new Label("        修改 按钮：修改事件"));
        grid.addRow(grid.getRowCount() ,new Label("        移除 按钮：移除事件"));
        grid.addRow(grid.getRowCount() ,new Label("        右键表格行：弹出快捷按钮"));

        dialog.getDialogPane().setContent(grid);

        Optional<?> result = dialog.showAndWait();
        result.ifPresent(o -> {

        });
    }
    @FXML
    void shortcutKeys(ActionEvent event){
        Dialog<?> dialog = new Dialog<>();

        Window window = dialog.getDialogPane().getScene().getWindow();
        Stage stage = (Stage) window;
        stage.getIcons().add(new Image("dialog.png"));

        dialog.setTitle("快捷键");

        ButtonType sureButton = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(sureButton);
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        grid.addRow(0,new Label("Ctrl+Shift+I"),new Label("开始收集"));
        grid.addRow(2,new Label("连按两次Esc"),new Label("停止执行/收集"));

        dialog.getDialogPane().setContent(grid);

        Optional<?> result = dialog.showAndWait();
        result.ifPresent(o -> {

        });
    }

    public void addEventClick(JinTaskGroup group,Integer defaultAddressValue){
        Label address = new Label("排序");
        NumberField addressValue = new NumberField();
        addressValue.setValue(defaultAddressValue);
        ChoiceBox<CustomEvent> typeValue = new ChoiceBox<>();
        ObservableList<CustomEvent> items = FXCollections.observableArrayList(CustomEvent.CUSTOM_EVENTS);
        typeValue.setConverter(new StringConverter<CustomEvent>() {
            @Override
            public String toString(CustomEvent customEvent) {
                return customEvent == null ? "" : customEvent.getName();
            }
            @Override
            public CustomEvent fromString(String s) {
                return null;
            }
        });
        JinUtils.getDialog("新增事件",(grid,dialog)->{
            grid.addRow(0,address,addressValue);
            Label type = new Label("类型");
            typeValue.setItems(items);
            grid.addRow(1,type, typeValue);
            typeValue.setSelectionModel(new ChoiceBoxSelectModel<>(typeValue, ()->{
                System.out.println(1);
            },param->{
                grid.getChildren().removeIf(node -> grid.getChildren().indexOf(node) >= 4);
                param.initAddPanel(grid);
            }));
            typeValue.setValue(items.get(0));
        },()->{
            if(addressValue.getValue() == null){
                JinUtils.error("排序不能为空");
            }
            CustomEvent value = typeValue.getValue();

            int index;
            int addressIndex = addressValue.getValue();
            if(addressIndex <= 0){
                index = 0;
            }else if(addressIndex > group.getEvents().size()){
                index = group.getEvents().size() + 1;
            }else {
                index = addressIndex;
            }
            IEvent event = value.fullAddIEvent();
            group.getEvents().add(index,event);
            group.getTableView().setItems(FXCollections.observableList(group.getEvents()));

        });

    }
    @FXML
    void addTaskClick(ActionEvent event) {
        TextInputDialog dialog = new TextInputDialog();
        dialog.setTitle("新增任务");
        dialog.setHeaderText("任务名不能为空");
        dialog.setContentText("任务名称");
        TextField editor = dialog.getEditor();
        Button okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
        okButton.setMouseTransparent(true);
        // 监听文本更改
        editor.textProperty().addListener((observable, oldValue, newValue) -> {
            if(newValue != null && !"".equals(newValue)){
                boolean flag = DataUtils.checkNameRepeat(newValue);
                if(flag){
                    okButton.setMouseTransparent(false);
                    dialog.setHeaderText("任务名可用");
                }else{
                    okButton.setMouseTransparent(true);
                    dialog.setHeaderText("任务名已存在");
                }
            }else{
                okButton.setMouseTransparent(true);
                dialog.setHeaderText("任务名不能为空");
            }
        });

        Optional<String> result = dialog.showAndWait();

        result.ifPresent(val->{
            JinTask task = DataUtils.addJinTask(val);
            refreshChoiceBox();
            taskChoice.setValue(task);
        });

    }
    @FXML
    void removeTaskClick(ActionEvent event) {
        JinTask value = taskChoice.getValue();
        JinTask task = DataUtils.removeTask(value);
        refreshChoiceBox();
        taskChoice.setValue(task);
    }
    @FXML
    void refreshTaskClick(ActionEvent event) {
        DataUtils.loadData();
        refreshChoiceBox();
        taskChoice.setValue(DataUtils.getFirstCopyTask());
    }
    @FXML
    void saveTaskClick(ActionEvent event) {
        DataUtils.saveData();
    }
    @FXML
    void collectClick(ActionEvent event) {
        startCollect(null,null);
    }
    private void startCollect(JinTaskGroup jinTaskGroup,TableView<IEvent> tableView){
        if(collectingFlag) return;
        if(!ThreadUtils.executable()){
            return;
        }
        // 键盘监听器
        keyboardListener = new KeyboardListener();
        // 监听鼠标点击
        mouseClickedListener = new MouseClickedListener();
        // 监听移动鼠标
        mouseMotionListener = new MouseMotionListener();

        GlobalScreen.addNativeMouseListener(mouseClickedListener);
        GlobalScreen.addNativeMouseMotionListener(mouseMotionListener);
        GlobalScreen.addNativeKeyListener(keyboardListener);

        if(jinTaskGroup == null){
            jinTaskGroup = new JinTaskGroup("分组");
        }
        CurrentStateUtil.startCollect(jinTaskGroup,tableView,System.currentTimeMillis());
        JinTaskApplication.STAGE.setIconified(true);
        FxJinTask<?> task = new FxJinTask<Object>() {
            @Override
            protected Object call() throws Exception {
                while (true){
                    if(isCancelled()){
                        break;
                    }
                }
                return null;
            }
        };
        task.setOnCancelled(workerStateEvent -> {
            stopClick(null);
        });
        task.setType(0);
        task.start();
        CurrentStateUtil.setRunningJinTask(task);
        JIntellitype.getInstance().registerHotKey(2, 0,27); // esc
        collectingFlag = true;
    }

    @FXML
    void stopExecuteClick(ActionEvent event){
        FxJinTask<?> runningJinTask = CurrentStateUtil.getRunningJinTask();
        if(runningJinTask != null){
            if(runningJinTask.getType() != 1){
                return;
            }
            JIntellitype.getInstance().unregisterHotKey(3); // esc
            runningJinTask.cancel();
        }
    }
    private void initExecuteChoiceBox(List<JinTaskGroup> groups,ChoiceBox<JinTaskGroup> groupBox,AtomicInteger groupIndex,NumberField numberField){
        groupBox.setStyle("-fx-pref-width: 200px");
        groupBox.setSelectionModel(new ChoiceBoxSelectModel<>(groupBox,()->{
            groupIndex.set(-1);
            numberField.setMin(0);
            numberField.setMax(0);
            numberField.setValue(0);
        },(group)->{
            groupIndex.set(groups.indexOf(group));
            numberField.setMin(0);
            numberField.setMax(group.getEvents().size() - 1);
            numberField.setValue(group.getEvents().size() - 1);
        }));
        groupBox.setConverter(new StringConverter<JinTaskGroup>() {
            @Override
            public String toString(JinTaskGroup object) {
                if(object == null) return null;
                return object.getComments();
            }

            @Override
            public JinTaskGroup fromString(String string) {
                return null;
            }
        });
        groupBox.setItems(FXCollections.observableList(groups));
    }
    void executeClickHelp(Integer startGroupIndex,Integer startEventIndex){
        AtomicInteger startGroupIndexAI = new AtomicInteger(-1);
        NumberField startEventNumber = new NumberField(0);
        AtomicInteger endGroupIndex = new AtomicInteger(-1);
        NumberField endEventNumber = new NumberField(0);
        startEventNumber.setMin(0);
        startEventNumber.setMax(0);
        JinUtils.getDialog("执行范围",(grid,dialog)->{
            JinTask jinTask = CurrentStateUtil.getSelectTask();
            List<JinTaskGroup> groups = jinTask.getGroups();

            ChoiceBox<JinTaskGroup> startGroupBox = new ChoiceBox<>();
            initExecuteChoiceBox(groups,startGroupBox,startGroupIndexAI,startEventNumber);

            startGroupBox.setValue(groups.get(Objects.requireNonNullElse(startGroupIndex, 0)));

            if(startEventIndex != null){
                startEventNumber.setValue(startEventIndex);
            }

            ChoiceBox<JinTaskGroup> endGroupBox = new ChoiceBox<>();
            initExecuteChoiceBox(groups,endGroupBox,endGroupIndex,endEventNumber);
            JinTaskGroup endJinGroup = groups.get(groups.size() - 1);
            endGroupBox.setValue(endJinGroup);
            endEventNumber.setValue(endJinGroup.getEvents().size() > 0 ? endJinGroup.getEvents().size() - 1 : 0);


            grid.addRow(0,new Label("开始 组"),startGroupBox);
            grid.addRow(1,new Label("开始 排序"),startEventNumber);

            grid.addRow(2,new Label("结束 组"),endGroupBox);
            grid.addRow(3,new Label("结束 排序"),endEventNumber);
        },()->{
            if(startGroupIndexAI.get() > endGroupIndex.get()){
                JinUtils.error("开始组应小于等于结束组");
                return;
            }else if(startGroupIndexAI.get() == endGroupIndex.get()){
                if(startEventNumber.getNullDefaultValue() > endEventNumber.getNullDefaultValue()){
                    JinUtils.error("开始排序应小于等于结束排序");
                    return;
                }
            }
            if(!ThreadUtils.executable()){
                return;
            }
            RunJinTask runJinTask = new RunJinTask(startGroupIndexAI.get(),startEventNumber.getNullDefaultValue(),
                    endGroupIndex.get(),endEventNumber.getNullDefaultValue());

            FxJinTask<String> task = new FxJinTask<String>() {
                @Override
                protected String call() {
                    runJinTask.execute(this);
                    return null;
                }
            };
            task.setOnCancelled(workerStateEvent -> {
                RunJinTask.robot.keyRelease(KeyEvent.VK_CONTROL);
                RunJinTask.robot.keyRelease(KeyEvent.VK_ALT);
                RunJinTask.robot.keyRelease(KeyEvent.VK_WINDOWS);
                JinTaskApplication.STAGE.setIconified(false);
                JinUtils.alert(String.format("主动中断任务【%s】,时间【%s】",
                        CurrentStateUtil.getSelectTask().getName(),
                        LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            });
            task.setOnFailed(workerStateEvent->{
                LogUtil.error("执行任务【%s】异常,时间【%s】",workerStateEvent.getSource().getException());
                JinTaskApplication.STAGE.setIconified(false);
                JinUtils.alert(String.format("执行任务【%s】异常,时间【%s】",
                        CurrentStateUtil.getSelectTask().getName(),
                        LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            });
            task.setOnSucceeded(workerStateEvent -> {
                LogUtil.error("执行任务【%s】异常,时间【%s】",workerStateEvent.getSource().getException());
                JinUtils.alert(String.format("执行任务【%s】完成,时间【%s】",
                        CurrentStateUtil.getSelectTask().getName(),
                        LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            });
            CurrentStateUtil.setRunningJinTask(task);

            JIntellitype.getInstance().registerHotKey(3, 0,27); // esc
            JinTaskApplication.STAGE.setIconified(true);
            task.setType(1);
            task.start();
        });
    }
    @FXML
    void executeClick(ActionEvent event) {
        executeClickHelp(null,null);
    }

    @FXML
    void stopClick(ActionEvent event) {
        if(!collectingFlag) return;
        collectingFlag = false;
        JIntellitype.getInstance().unregisterHotKey(2); // esc
        mouseMotionListener.destroy();
        GlobalScreen.removeNativeMouseListener(mouseClickedListener);
        GlobalScreen.removeNativeKeyListener(keyboardListener);
        CurrentStateUtil.stopCollect();
        JinTaskApplication.STAGE.setIconified(false);
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    private static final DataFormat SERIALIZED_MIME_TYPE = new DataFormat("application/x-java-serialized-object");


    public void initTablePane(JinTask jinTask){
        accordion.getPanes().clear();
        CustomEvent.LOOP_EVENTS.clear();
        List<JinTaskGroup> groups = jinTask.getGroups();
        for (int i = 0; i < groups.size(); i++) {
            JinTaskGroup item = groups.get(i);
            TableView<IEvent> tableView = new TableView<>();
            item.setTableView(tableView);
            TableColumn<IEvent,Integer> orderNum = new TableColumn<>("排序");
            TableColumn<IEvent,Pane> action = new TableColumn<>("事件");
            TableColumn<IEvent,Pane> operation = new TableColumn<>("操作");
            tableColumnProperty(tableView,item,orderNum,action,operation);
            tableView.getColumns().addAll(orderNum,action,operation);
            tableView.setItems(FXCollections.observableList(item.getEvents()));
            TitledPane pane = new TitledPane(item.getComments() , tableView);
            final int paneIndex = i;

            //拖拽-检测
            pane.setOnDragDetected(event -> {
                Dragboard db = pane.startDragAndDrop(TransferMode.MOVE);
                db.setDragView(pane.snapshot(null, null));
                ClipboardContent cc = new ClipboardContent();
                cc.put(SERIALIZED_MIME_TYPE, paneIndex);
                db.setContent(cc);
                event.consume();
            });
            //释放-验证
            pane.setOnDragOver(event -> {
                Dragboard db = event.getDragboard();
                if (db.hasContent(SERIALIZED_MIME_TYPE)) {
                    if (paneIndex != (Integer) db.getContent(SERIALIZED_MIME_TYPE)) {
                        event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                        event.consume();
                    }
                }
            });
            //释放-执行
            pane.setOnDragDropped(event -> {
                Dragboard db = event.getDragboard();
                if (db.hasContent(SERIALIZED_MIME_TYPE)) {
                    int draggedIndex = (Integer) db.getContent(SERIALIZED_MIME_TYPE);
                    TitledPane titledPane = accordion.getPanes().remove(draggedIndex);
                    accordion.getPanes().add(paneIndex, titledPane);
                    event.setDropCompleted(true);
                    List<JinTaskGroup> changeGroups = jinTask.getGroups();
                    JinTaskGroup jinTaskGroup = changeGroups.get(draggedIndex);
                    changeGroups.remove(draggedIndex);
                    changeGroups.add(paneIndex,jinTaskGroup);
                    event.consume();
                }
            });


            tableView.setRowFactory(tv -> {
                TableRow<IEvent> row = new TableRow<>();

                ContextMenu contextMenu = new ContextMenu();
                row.setOnMousePressed((event)->{
                    if (event.getButton() == MouseButton.SECONDARY){

                        int index = row.getIndex();
                        MenuItem menuItem1 = new MenuItem("上方新增事件");
                        menuItem1.setOnAction(e -> addEventClick(item,index));

                        MenuItem menuItem2 = new MenuItem("下方新增事件");
                        menuItem2.setOnAction(e -> addEventClick(item,index+1));

                        MenuItem menuItem3 = new MenuItem("此处开始执行");
                        menuItem3.setOnAction(e -> executeClickHelp(paneIndex,index));

                        contextMenu.getItems().clear();
                        contextMenu.getItems().addAll(menuItem1, menuItem2,menuItem3);

                        contextMenu.show(row, event.getScreenX(), event.getScreenY());
                    }
                });
                //拖拽-检测
                row.setOnDragDetected(event -> {
                    if (!row.isEmpty()) {
                        Integer index = row.getIndex();
                        Dragboard db = row.startDragAndDrop(TransferMode.MOVE);
                        db.setDragView(row.snapshot(null, null));
                        ClipboardContent cc = new ClipboardContent();
                        cc.put(SERIALIZED_MIME_TYPE, index);
                        db.setContent(cc);
                        event.consume();
                    }
                });
                //释放-验证
                row.setOnDragOver(event -> {
                    Dragboard db = event.getDragboard();
                    if (db.hasContent(SERIALIZED_MIME_TYPE)) {
                        if (row.getIndex() != (Integer) db.getContent(SERIALIZED_MIME_TYPE)) {
                            event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                            event.consume();
                        }
                    }
                });
                //释放-执行
                row.setOnDragDropped(event -> {
                    Dragboard db = event.getDragboard();
                    if (db.hasContent(SERIALIZED_MIME_TYPE)) {
                        int draggedIndex = (Integer) db.getContent(SERIALIZED_MIME_TYPE);
                        IEvent iEvent = tableView.getItems().remove(draggedIndex);

                        int dropIndex;
                        if (row.isEmpty()) {
                            dropIndex = tableView.getItems().size();
                        } else {
                            dropIndex = row.getIndex();
                        }

                        tableView.getItems().add(dropIndex, iEvent);

                        event.setDropCompleted(true);
                        tableView.getSelectionModel().select(dropIndex);
                        event.consume();
                    }
                });

                return row;
            });

            Button addEvent = new Button("新增事件");
            Button comments = new Button("备注");
            Button collect = new Button("收集");
            Button remove = new Button("移除");
            addEvent.setOnAction(event -> {
                addEventClick(item,null);
            });
            remove.setOnAction(event -> {
                CurrentStateUtil.getSelectTask().removeTaskGroup(item);
                JinTaskController.controller.initTablePane(CurrentStateUtil.getSelectTask());

            });
            collect.setOnAction(event -> {
                startCollect(item,tableView);
            });
            comments.setOnAction(event -> {
                TextField commentsField = new TextField();
                commentsField.setText(item.getComments());
                JinUtils.getDialog("修改备注",(grid,dialog)->{
                    grid.add(new Label("备注:"), 0, 0);
                    grid.add(commentsField, 1, 0);
                },()->{
                    pane.textProperty().setValue(commentsField.getText());
                    item.setComments(commentsField.getText());
                });

            });
            HBox right = new HBox();
            right.getChildren().addAll(addEvent,collect,comments,remove);
            pane.setGraphic(right);
            pane.setContentDisplay(ContentDisplay.RIGHT);

            final double graphicMarginRight = 10; //change it, if needed

            right.translateXProperty().bind(Bindings.createDoubleBinding(
                    () -> pane.getWidth() - right.getLayoutX() - right.getWidth() - graphicMarginRight,
                    pane.widthProperty())
            );

            pane.getContent().setStyle("-fx-min-height: 300;-fx-padding: 0 0 0 10;");

            accordion.getPanes().add(pane);
        }
    }
    private void tableColumnProperty(TableView<IEvent> tableView,JinTaskGroup group,TableColumn<IEvent,Integer> orderNum,TableColumn<IEvent,Pane> action,TableColumn<IEvent,Pane> operation){
        orderNum.setSortable(false);
        action.setSortable(false);
        operation.setSortable(false);
        orderNum.setStyle("-fx-alignment: center ;");
        orderNum.setCellValueFactory(param -> new SimpleIntegerProperty( param.getTableView().getItems().indexOf(param.getValue()) ).asObject());
        action.setCellValueFactory(e -> new ObservableValue<Pane>() {
            @Override
            public void addListener(ChangeListener<? super Pane> changeListener) {

            }

            @Override
            public void removeListener(ChangeListener<? super Pane> changeListener) {

            }

            @Override
            public Pane getValue() {
                return e.getValue().initDesc();
            }

            @Override
            public void addListener(InvalidationListener invalidationListener) {

            }

            @Override
            public void removeListener(InvalidationListener invalidationListener) {

            }
        });
        operation.setCellValueFactory(e -> new ObservableValue<Pane>() {
            @Override
            public void addListener(InvalidationListener invalidationListener) {

            }

            @Override
            public void removeListener(InvalidationListener invalidationListener) {

            }

            @Override
            public void addListener(ChangeListener<? super Pane> changeListener) {

            }

            @Override
            public void removeListener(ChangeListener<? super Pane> changeListener) {

            }

            @Override
            public Pane getValue() {
                IEvent value = e.getValue();
                BorderPane pane = new BorderPane();
                HBox vBox = new HBox();
                Button edit = new Button("修改");
                Button remove = new Button("移除");
                if(value.getLuaFlag()){
                    edit.setBackground(new Background(new BackgroundFill(Color.YELLOWGREEN,null,null)));
                }
                if(value instanceof LoopEndEvent){
                    vBox.getChildren().addAll(remove);
                }else{
                    vBox.getChildren().addAll(edit,remove);
                }
                pane.setCenter(vBox);
                remove.setOnAction(actionEvent -> {
                    CustomEvent.removeLoopEvent(value);
                    group.getEvents().remove(value);
                    tableView.setItems(FXCollections.observableList(group.getEvents()));
                });
                AtomicReference<CustomEvent> updateCustom = new AtomicReference<>();
                edit.setOnAction(actionEvent -> {
                    JinUtils.getDialog("修改事件,排序：" + orderNum.getCellObservableValue(value).getValue(),(grid,dialog)->{
                        updateCustom.set(CustomEvent.initEditPane(grid, value));
                    },()->{
                        updateCustom.get().fullEditIEvent();
                        tableView.refresh();
                    });
                });
                return pane;
            }
        });
    }
    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        taskChoice.setConverter(new StringConverter<JinTask>() {
            @Override
            public String toString(JinTask task) {
                if(task == null) {
                    return null;
                }
                return task.getName();
            }

            @Override
            public JinTask fromString(String s) {
                return DataUtils.getTask(s);
            }
        });
        ObservableList<JinTask> jinTasks = FXCollections.observableArrayList(DataUtils.getJinTaskList());
        taskChoice.setItems(jinTasks);
        taskChoice.setSelectionModel(new ChoiceBoxSelectModel<>(taskChoice,()->{
            buttonUnEnableClick();
        }, param -> {
            buttonEnableClick();
            CurrentStateUtil.setSelectTask(param);
        }));
        taskChoice.getSelectionModel().select(0);

        buttonUnEnableClick();

        registerHotKey();
        // 注册全局鼠标、键盘监听
        registerNativeHook();

        registerCustomEvent();
    }
    /** 注册手工可添加事件 **/
    private void registerCustomEvent(){
        CustomEvent.registerCustomEvent(new CustomLoopStartEvent());
        CustomEvent.registerCustomEvent(new CustomLoopEndEvent());
        CustomEvent.registerCustomEvent(new CustomInputStringEvent());
        CustomEvent.registerCustomEvent(new CustomMousePressedEvent());
        CustomEvent.registerCustomEvent(new CustomMouseReleasedEvent());
        CustomEvent.registerCustomEvent(new CustomMouseMotionEvent());
        CustomEvent.registerCustomEvent(new CustomKeyPressEvent());
        CustomEvent.registerCustomEvent(new CustomKeyReleasedEvent());
        CustomEvent.registerCustomEvent(new CustomSleepEvent());
    }

    public void refreshChoiceBox(){
        ObservableList<JinTask> copyTasks = FXCollections.observableArrayList(DataUtils.getJinTaskList());
        taskChoice.setItems(copyTasks);
    }

    private void buttonEnableClick(){
        collect.setMouseTransparent(false);
        stop.setMouseTransparent(false);
        execute.setMouseTransparent(false);
        stopExecute.setMouseTransparent(false);
    }
    private void buttonUnEnableClick(){
        collect.setMouseTransparent(true);
        stop.setMouseTransparent(true);
        execute.setMouseTransparent(true);
        stopExecute.setMouseTransparent(true);
    }

    private void registerNativeHook() {
        // 注册全局监听
        try {
            GlobalScreen.registerNativeHook();
        } catch (NativeHookException e) {
            LogUtil.error("注册全局监听",e);
        }
        Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
        logger.setLevel(Level.OFF);
    }


    public void registerHotKey(){
        EasyData<Long> preEscTime = new EasyData<>(0L);
        // 开始收集
        JIntellitype.getInstance().registerHotKey(1, JIntellitype.MOD_CONTROL+JIntellitype.MOD_SHIFT, (int)'I');

        JIntellitype.getInstance().addHotKeyListener(identifier -> {
            if(1 == identifier){
                collectClick(null);
            }else if(identifier == 2){
                long nowEscTime = System.currentTimeMillis();
                if(nowEscTime - preEscTime.getVal() <= 500){
                    CurrentStateUtil.getRunningJinTask().stop();
                    preEscTime.setVal(0L);
                }else{
                    preEscTime.setVal(nowEscTime);
                }
            }else if(identifier == 3){
                long nowEscTime = System.currentTimeMillis();
                if(nowEscTime - preEscTime.getVal() <= 500){
                    stopExecuteClick(null);
                    preEscTime.setVal(0L);
                }else{
                    preEscTime.setVal(nowEscTime);
                }
            }
        }); // 添加监听
    }
}